﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using Coolite.Ext.Web;
using Pap.Web.Modules.Reports.ViewModel;
using Pap.Web.Utils;

namespace Pap.Web.Modules.Reports.Views
{
    /// <summary>
    /// 
    /// </summary>
    public partial class StatisticsReport : BasePage<StatisticsReportViewModel>
    {
        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.Master.GenerateReport += Master_GetReport;
            if (!IsPostBack && !Ext.IsAjaxRequest)
            {
                FillReportParams();
            }
        }

        /// <summary>
        /// Fills the report params.
        /// </summary>
        private void FillReportParams()
        {
            strProjects.DataSource = this.ViewModel.GetAllProjects();
            strProjects.DataBind();
        }

        /// <summary>
        /// Handles the GetReport event of the Master control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void Master_GetReport(object sender, EventArgs e)
        {
            AjaxEventArgs args = (AjaxEventArgs)e;

            DateTime dateLimit = Convert.ToDateTime(dtDateLimit.Value);
            Guid projectID = cmbProjects.SelectedItem.Value.ToGuid();

            lblMonth.Text = dateLimit.ToString("dd/MM/yyyy");
            lblProject.Text = cmbProjects.SelectedItem.Text;

            double loanCount = this.ViewModel.GetLoanCount(projectID, dateLimit);

            args.ExtraParamsResponse.Add(GetGenderPercentReport(projectID, dateLimit));
            args.ExtraParamsResponse.Add(GetGenderActivityPercentReport(projectID, dateLimit, loanCount));
            args.ExtraParamsResponse.Add(GetActivitiesPercentReport(projectID, dateLimit, loanCount));
            args.ExtraParamsResponse.Add(GetLoanStatusPercentReport(projectID, dateLimit));
        }

        /// <summary>
        /// Gets the gender percent report.
        /// </summary>
        /// <param name="projectID">The project ID.</param>
        /// <param name="dateLimit">The date limit.</param>
        private Parameter GetGenderPercentReport(Guid projectID, DateTime dateLimit)
        {
            double[] yValues;
            string[] xValues;
            double result = this.ViewModel.GetMalePercent(projectID, dateLimit);

            yValues = new double[] { result * 100, 100 - result * 100 };
            xValues = new string[] { "Males", "Females" };

            string renderedControl = ConfigureChartControl(chrtGenderPercent, yValues, xValues, chrtGenderPercent.Titles.FindByName("Title1").Text);
            return new Parameter(chrtGenderPercent.ClientID, renderedControl);
        }

        /// <summary>
        /// Gets the gender activity percent report.
        /// </summary>
        /// <param name="projectID">The project ID.</param>
        /// <param name="dateLimit">The date limit.</param>
        /// <param name="loanCount">The loan count.</param>
        private Parameter GetGenderActivityPercentReport(Guid projectID, DateTime dateLimit, double loanCount)
        {
            List<double> ys = new List<double>();
            List<string> xs = new List<string>();
            IEnumerable values = this.ViewModel.GetMaleActivity(projectID, dateLimit);
            foreach (var item in values)
            {
                ys.Add(Convert.ToDouble(DataBinder.Eval(item, "Count")) / loanCount * 100);
                xs.Add(DataBinder.Eval(item, "Gender") + " - " + DataBinder.Eval(item, "TypeName"));
            }
            var renderedControl = ConfigureChartControl(chrtGenderActivity, ys.ToArray(), xs.ToArray(),
                                                        chrtGenderActivity.Titles.FindByName("Title1").Text);
            return new Parameter(chrtGenderActivity.ClientID, renderedControl);
        }

        /// <summary>
        /// Gets the activities percent report.
        /// </summary>
        /// <param name="projectID">The project ID.</param>
        /// <param name="dateLimit">The date limit.</param>
        /// <param name="loanCount">The loan count.</param>
        private Parameter GetActivitiesPercentReport(Guid projectID, DateTime dateLimit, double loanCount)
        {
            List<double> ys = new List<double>();
            List<string> xs = new List<string>();

            IEnumerable values = this.ViewModel.GetAcitivtyPercents(projectID, dateLimit);

            foreach (var item in values)
            {
                ys.Add(Convert.ToDouble(DataBinder.Eval(item, "Count")) / loanCount * 100);
                xs.Add(DataBinder.Eval(item, "TypeName").ToString());
            }
            var renderedControl = ConfigureChartControl(chrtActivity, ys.ToArray(), xs.ToArray(), chrtActivity.Titles.FindByName("Title1").Text);
            return new Parameter(chrtActivity.ClientID, renderedControl);
        }

        /// <summary>
        /// Gets the loan status percent report.
        /// </summary>
        /// <param name="projectID">The project ID.</param>
        /// <param name="dateLimit">The date limit.</param>
        private Parameter GetLoanStatusPercentReport(Guid projectID, DateTime dateLimit)
        {
            double[] yValues;
            string[] xValues;
            double result = this.ViewModel.GetExistingLoans(projectID, dateLimit);

            yValues = new double[] { result * 100, 100 - result * 100 };
            xValues = new string[] { "Exisiting", "New" };
            var renderedControl = ConfigureChartControl(chrtLoanStatus, yValues, xValues, chrtActivity.Titles.FindByName("Title1").Text);
            return new Parameter(chrtLoanStatus.ClientID, renderedControl);
        }

        /// <summary>
        /// Configures the chart control.
        /// </summary>
        /// <param name="chart">The chart.</param>
        /// <param name="yValues">The y values.</param>
        /// <param name="xValues">The x values.</param>
        /// <param name="title">The title.</param>
        private string ConfigureChartControl(Chart chart, double[] yValues, string[] xValues, string title)
        {
            chart.Series["Default"].Points.DataBindXY(xValues, yValues);
            chart.Series["Default"].ChartType = SeriesChartType.Pie;
            chart.Series["Default"]["PieLabelStyle"] = "Disabled";
            // Set chart type and title
            chart.Series["Default"].ChartType = SeriesChartType.Pie;
            chart.Titles[0].Text = title;
            // Set labels style
            chart.Series["Default"]["PieLabelStyle"] = "Outside";
            // Enable 3D
            chart.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true;
            //chart.Series[0]["PieDrawingStyle"] = "Default";
            chart.Legends[0].Enabled = true;
            // Explode parts
            foreach (DataPoint point in chart.Series["Default"].Points)
            {
                point["Exploded"] = "true";
            }

            //--- generate image tag for ajax responce. ---
            // stupid workaround to get the newly generated imageUrl, Chart control dosent support returing back the generated url....

            var writer = new HtmlTextWriter(new StringWriter());
            chart.RenderControl(writer);
            return
                Regex.Match(writer.InnerWriter.ToString(), @"(?<=<img\s+[^>]*?src=(?<q>['""""]))(?<url>.+?)(?=\k<q>)",
                            RegexOptions.IgnoreCase).Value;
        }
    }
}
